package com.wechat.gateway;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 网关过滤器测试工具
 */
@Slf4j
public class FilterTestUtil {

    private static final String GATEWAY_URL = "http://localhost:8080";

    /**
     * 测试获取RSA公钥
     */
    public static String getPublicKey() {
        try {
            String url = GATEWAY_URL + "/crypto/public-key";
            HttpResponse response = HttpRequest.get(url).execute();

            if (response.isOk()) {
                JSONObject result = JSONUtil.parseObj(response.body());
                JSONObject data = result.getJSONObject("data");
                String publicKey = data.getStr("publicKey");

                log.info("获取RSA公钥成功");
                log.info("公钥: {}", publicKey);

                return publicKey;
            } else {
                log.error("获取公钥失败: {}", response.body());
                return null;
            }
        } catch (Exception e) {
            log.error("获取公钥异常: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 测试加密解密功能
     */
    public static boolean testCrypto() {
        try {
            String url = GATEWAY_URL + "/crypto/test";
            JSONObject requestData = new JSONObject();
            requestData.put("plainText", "Hello, WeChat Gateway!");
            HttpResponse response = HttpRequest.post(url)
                    .header("Content-Type", "application/json")
                    .body(requestData.toString())
                    .execute();

            if (response.isOk()) {
                JSONObject result = JSONUtil.parseObj(response.body());
                JSONObject data = result.getJSONObject("data");
                boolean testResult = data.getBool("testResult");

                log.info("加密解密测试结果: {}", testResult ? "成功" : "失败");
                log.info("原文: {}", data.getStr("originalText"));
                log.info("密文: {}", data.getStr("encryptedText"));
                log.info("解密: {}", data.getStr("decryptedText"));

                return testResult;
            } else {
                log.error("加密解密测试失败: {}", response.body());
                return false;
            }
        } catch (Exception e) {
            log.error("加密解密测试异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 测试使用公钥加密数据
     */
    public static String encryptWithPublicKey(String publicKeyStr, String plainText) {
        try {
            RSA rsa = SecureUtil.rsa(null, publicKeyStr);
            return rsa.encryptBase64(plainText, cn.hutool.crypto.asymmetric.KeyType.PublicKey);
        } catch (Exception e) {
            log.error("使用公钥加密失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 测试Token验证（模拟登录请求）
     */
    public static boolean testTokenValidation() {
        try {
            // 1. 先测试登录接口（应该在白名单中）
            String loginUrl = GATEWAY_URL + "/user/login/phone";
            JSONObject loginData = new JSONObject();
            loginData.put("phone", "15351296334");
            loginData.put("password", "aA3.1415926");

            HttpResponse loginResponse = HttpRequest.post(loginUrl)
                    .header("Content-Type", "application/json")
                    .body(loginData.toString())
                    .execute();

            log.info("登录请求响应: {}", loginResponse.body());

            // 2. 测试需要token的接口
            String protectedUrl = GATEWAY_URL + "/user/profile";

            // 不带token的请求
            HttpResponse noTokenResponse = HttpRequest.get(protectedUrl).execute();
            log.info("不带token的请求响应: {}", noTokenResponse.body());

            // 带无效token的请求
            HttpResponse invalidTokenResponse = HttpRequest.get(protectedUrl)
                    .header("Authorization", "Bearer invalid_token")
                    .execute();
            log.info("带无效token的请求响应: {}", invalidTokenResponse.body());

            return true;
        } catch (Exception e) {
            log.error("Token验证测试异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 测试限流功能 - 测试登录接口限流
     */
    public static boolean testRateLimit() {
        try {
            String loginUrl = GATEWAY_URL + "/user/login/phone";
            JSONObject loginData = new JSONObject();
            loginData.put("phone", "15351296334");
            loginData.put("password", "aA3.1415926");

            log.info("开始测试登录接口限流功能...");
            log.info("根据配置，登录接口限流规则：capacity=5, refillRate=0.1/s, dimension=IP");

            int successCount = 0;
            int rateLimitCount = 0;
            int totalRequests = 8; // 发送8个请求，应该有3个被限流

            // 快速发送多个登录请求
            for (int i = 1; i <= totalRequests; i++) {
                HttpResponse response = HttpRequest.post(loginUrl)
                        .header("Content-Type", "application/json")
                        .body(loginData.toString())
                        .timeout(5000)
                        .execute();

                log.info("第{}次请求 - 状态码: {}", i, response.getStatus());

                if (response.getStatus() == 429) {
                    // HTTP 429 Too Many Requests - 被限流
                    rateLimitCount++;
                    log.info("第{}次请求被限流: {}", i, response.body());
                } else if (response.isOk()) {
                    successCount++;
                    log.info("第{}次请求成功", i);
                } else {
                    log.info("第{}次请求失败，状态码: {}, 响应: {}", i, response.getStatus(), response.body());
                }

                // 短暂间隔，避免请求过快导致其他问题
                Thread.sleep(100);
            }

            log.info("限流测试结果统计:");
            log.info("总请求数: {}", totalRequests);
            log.info("成功请求数: {}", successCount);
            log.info("被限流请求数: {}", rateLimitCount);

            // 验证限流是否按预期工作
            boolean rateLimitWorking = rateLimitCount > 0; // 应该有请求被限流

            if (rateLimitWorking) {
                log.info("✓ 限流功能正常工作，有{}个请求被限流", rateLimitCount);

                // 等待一段时间，测试令牌恢复
                log.info("等待10秒，测试令牌恢复...");
                Thread.sleep(10000);

                // 再次发送请求，应该能成功
                HttpResponse recoveryResponse = HttpRequest.post(loginUrl)
                        .header("Content-Type", "application/json")
                        .body(loginData.toString())
                        .timeout(5000)
                        .execute();

                log.info("恢复测试 - 状态码: {}", recoveryResponse.getStatus());

                if (recoveryResponse.getStatus() != 429) {
                    log.info("✓ 令牌恢复测试通过，限流已恢复正常");
                    return true;
                } else {
                    log.warn("✗ 令牌恢复测试失败，仍然被限流");
                    return false;
                }
            } else {
                log.warn("✗ 限流功能可能未正常工作，没有请求被限流");
                return false;
            }

        } catch (Exception e) {
            log.error("限流测试异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 完整的功能测试
     */
    public static void runAllTests() {
        log.info("=== 开始网关过滤器功能测试 ===");

        // 1. 测试获取公钥
        log.info("1. 测试获取RSA公钥...");
        String publicKey = getPublicKey();
        boolean publicKeyTest = publicKey != null;
        log.info("公钥获取测试: {}", publicKeyTest ? "通过" : "失败");

        // 2. 测试加密解密
        log.info("\n2. 测试加密解密功能...");
        boolean cryptoTest = testCrypto();
        log.info("加密解密测试: {}", cryptoTest ? "通过" : "失败");

        // 3. 测试Token验证
        log.info("\n3. 测试Token验证功能...");
        boolean tokenTest = testTokenValidation();
        log.info("Token验证测试: {}", tokenTest ? "通过" : "失败");

        // 4. 测试限流
        log.info("\n4. 测试限流功能...");
        boolean rateLimitTest = testRateLimit();
        log.info("限流测试: {}", rateLimitTest ? "通过" : "失败");

        // 5. 综合测试结果
        log.info("\n=== 测试结果汇总 ===");
        log.info("公钥获取: {}", publicKeyTest ? "✓" : "✗");
        log.info("加密解密: {}", cryptoTest ? "✓" : "✗");
        log.info("Token验证: {}", tokenTest ? "✓" : "✗");
        log.info("限流功能: {}", rateLimitTest ? "✓" : "✗");

        boolean allPassed = publicKeyTest && cryptoTest && tokenTest && rateLimitTest;
        log.info("整体测试: {}", allPassed ? "全部通过 ✓" : "部分失败 ✗");
    }

    /**
     * 主方法 - 运行测试
     */
    public static void main(String[] args) {
        runAllTests();
    }
} 